const schedule = require('node-schedule');
const { Warning, User } = require('../models');
const weatherApi = require('./weatherApi');
const emailService = require('./emailService');
const { Op } = require('sequelize');

// 存储所有定时任务的映射表
const scheduledTasks = new Map();

/**
 * 初始化预警任务调度器
 * 从数据库加载所有活跃的预警设置并创建定时任务
 */
exports.initWarningScheduler = async () => {
  try {
    console.log('正在初始化预警任务调度器...');
    
    // 从数据库获取所有活跃的预警设置
    const activeWarnings = await Warning.findAll({
      where: {
        isActive: true,
        triggerTime: {
          [Op.gt]: new Date() // 只获取未来时间的预警
        }
      },
      include: [{
        model: User,
        attributes: ['email', 'username']
      }]
    });
    
    console.log(`找到 ${activeWarnings.length} 个活跃的预警任务`);
    
    // 为每个预警创建定时任务
    activeWarnings.forEach(warning => {
      scheduleWarningTask(warning);
    });
    
    // 设置每小时检查一次即将到期的倒计时预警
    schedule.scheduleJob('0 * * * *', async () => {
      checkCountdownWarnings();
    });
    
    console.log('预警任务调度器初始化完成');
  } catch (error) {
    console.error('初始化预警任务调度器失败:', error);
  }
};

/**
 * 为单个预警创建定时任务
 * @param {Object} warning - 预警设置对象
 */
exports.scheduleWarningTask = scheduleWarningTask;
function scheduleWarningTask(warning) {
  try {
    // 如果该预警已有定时任务，先取消
    if (scheduledTasks.has(warning.id)) {
      scheduledTasks.get(warning.id).cancel();
    }
    
    // 创建新的定时任务
    if (warning.isCountdown && warning.countdownMinutes) {
      // 倒计时类型，计算触发时间
      const triggerTime = new Date();
      triggerTime.setMinutes(triggerTime.getMinutes() + warning.countdownMinutes);
      warning.triggerTime = triggerTime;
      
      // 保存更新后的触发时间
      warning.save();
    }
    
    // 如果触发时间已过，不创建任务
    if (new Date(warning.triggerTime) <= new Date()) {
      console.log(`预警 #${warning.id} 的触发时间已过，不创建任务`);
      return;
    }
    
    console.log(`为预警 #${warning.id} 创建定时任务，触发时间: ${warning.triggerTime}`);
    
    // 创建定时任务
    const job = schedule.scheduleJob(warning.triggerTime, async () => {
      await processWarningTask(warning.id);
    });
    
    // 存储任务引用
    scheduledTasks.set(warning.id, job);
  } catch (error) {
    console.error(`为预警 #${warning.id} 创建定时任务失败:`, error);
  }
}

/**
 * 处理预警任务，获取天气数据并发送邮件
 * @param {number} warningId - 预警ID
 */
async function processWarningTask(warningId) {
  try {
    console.log(`正在处理预警任务 #${warningId}`);
    
    // 从数据库获取最新的预警信息
    const warning = await Warning.findByPk(warningId, {
      include: [{
        model: User,
        attributes: ['email', 'username']
      }]
    });
    
    if (!warning || !warning.isActive) {
      console.log(`预警 #${warningId} 不存在或已停用`);
      return;
    }
    
    // 获取预警数据
    const warningData = await weatherApi.getWeatherWarnings(warning.location);
    
    // 发送邮件
    await emailService.sendWarningEmail({
      to: warning.User.email,
      subject: `${warning.locationName} 天气预警通知`,
      username: warning.User.username,
      location: warning.locationName,
      warnings: warningData.warning || []
    });
    
    // 更新预警的最后发送时间
    warning.lastSentAt = new Date();
    await warning.save();
    
    console.log(`预警任务 #${warningId} 处理完成`);
    
    // 如果是一次性预警，停用它
    if (!warning.isRecurring) {
      warning.isActive = false;
      await warning.save();
      
      // 删除任务
      if (scheduledTasks.has(warningId)) {
        scheduledTasks.delete(warningId);
      }
    }
  } catch (error) {
    console.error(`处理预警任务 #${warningId} 失败:`, error);
  }
}

/**
 * 检查即将到期的倒计时预警
 */
async function checkCountdownWarnings() {
  try {
    const now = new Date();
    const oneHourLater = new Date(now.getTime() + 60 * 60 * 1000);
    
    // 查找1小时内要触发的预警
    const upcomingWarnings = await Warning.findAll({
      where: {
        isActive: true,
        isCountdown: true,
        triggerTime: {
          [Op.gt]: now,
          [Op.lte]: oneHourLater
        }
      }
    });
    
    // 确保这些预警都有对应的定时任务
    upcomingWarnings.forEach(warning => {
      if (!scheduledTasks.has(warning.id)) {
        scheduleWarningTask(warning);
      }
    });
  } catch (error) {
    console.error('检查倒计时预警失败:', error);
  }
}

/**
 * 取消预警任务
 * @param {number} warningId - 预警ID
 */
exports.cancelWarningTask = async (warningId) => {
  try {
    if (scheduledTasks.has(warningId)) {
      scheduledTasks.get(warningId).cancel();
      scheduledTasks.delete(warningId);
      console.log(`预警任务 #${warningId} 已取消`);
    }
  } catch (error) {
    console.error(`取消预警任务 #${warningId} 失败:`, error);
  }
};

/**
 * 重新调度所有预警任务
 */
exports.rescheduleAllTasks = async () => {
  try {
    // 取消所有现有任务
    for (const [id, job] of scheduledTasks.entries()) {
      job.cancel();
      scheduledTasks.delete(id);
    }
    
    // 重新初始化
    await this.initWarningScheduler();
  } catch (error) {
    console.error('重新调度所有预警任务失败:', error);
  }
}; 